/**
 * 文件名：GlobalExceptionHandler.java
 * 功能：全局异常处理器
 * 作用：统一拦截和处理所有 Controller 抛出的异常，转换为统一的 ApiResponse 格式
 * 模块关系：
 *   - 拦截所有 Controller 异常：包括 AppController、AuthController、UserController 等
 *   - 依赖 ApiResponse：封装错误响应
 *   - 依赖 BusinessException：处理业务逻辑异常
 *   - 处理 Spring 内置异常：参数错误、404、500 等
 * 作者：白永康
 * 学号：2501210209
 */
package com.example.demo.common;

import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import org.springframework.web.servlet.NoHandlerFoundException;
import org.springframework.web.servlet.resource.NoResourceFoundException;

/**
 * 全局异常处理器
 * 使用 @RestControllerAdvice 注解自动拦截所有 REST 控制器中的异常
 */
@RestControllerAdvice
public class GlobalExceptionHandler {

    /**
     * 处理业务异常（主动抛出）
     * @param ex BusinessException 实例
     * @return 统一错误响应
     */
    @ExceptionHandler(BusinessException.class)
    public ApiResponse<Void> handleBiz(BusinessException ex) {
        return ApiResponse.fail(ex.getCode(), ex.getMessage());
    }

    /**
     * 处理 400 请求错误（参数缺失/类型不匹配/JSON 解析失败等）
     * @param ex 异常实例
     * @return 统一错误响应
     */
    @ExceptionHandler({
            MissingServletRequestParameterException.class,
            MethodArgumentTypeMismatchException.class,
            HttpMessageNotReadableException.class
    })
    public ApiResponse<Void> handleBadRequest(Exception ex) {
        return ApiResponse.fail(40000, ex.getMessage());
    }

    /**
     * 处理 404 资源不存在（Spring 6.1+ / Boot 3.2+ 默认抛出）
     * @param ex NoResourceFoundException 实例
     * @return 统一错误响应
     */
    @ExceptionHandler(NoResourceFoundException.class)
    public ApiResponse<Void> handleNoResource(NoResourceFoundException ex) {
        return ApiResponse.fail(40400, "资源不存在：" + ex.getResourcePath());
    }

    /**
     * 处理 404 路由不存在（兼容旧版本，某些场景仍可能出现）
     * @param ex NoHandlerFoundException 实例
     * @return 统一错误响应
     */
    @ExceptionHandler(NoHandlerFoundException.class)
    public ApiResponse<Void> handleNotFound(NoHandlerFoundException ex) {
        return ApiResponse.fail(40400, "资源不存在：" + ex.getRequestURL());
    }

    /**
     * 处理 500 服务器异常（兜底，未预料的异常）
     * @param ex 异常实例
     * @return 统一错误响应
     */
    @ExceptionHandler(Exception.class)
    public ApiResponse<Void> handleOthers(Exception ex) {
        // 生产环境建议记录日志/告警
        return ApiResponse.fail(50000, "服务器异常，请稍后再试");
    }
}
